<template>
    <div class="scene-wrapper" ref="mains" id="box">
    </div>
  </template>
  
  <script setup>
  import { onMounted } from 'vue'
  // 添加一个立方体
  import * as THREE from "three";
  import { OrbitControls } from "three/addons/controls/OrbitControls.js";
  
  onMounted(() => {
  var delta;
  var time;
  
  var vs = [];
  var fs = [];
  var mesh = [];
  var tex = [];
  var mat = [];
  
  var texture_loader = new THREE.TextureLoader();
  
  const DOM = document.querySelector("#box");
  const width = DOM.clientWidth;
  const height = DOM.clientHeight;
  
  const renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
  });
  renderer.setClearColor(0xb9eeff, 1);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(width, height, false);
  DOM.appendChild(renderer.domElement);
  
  const camera = new THREE.PerspectiveCamera(
      45,
      width / height,
      0.05,
      100000
  );
  camera.position.set(5,5,5)
  const scene = new THREE.Scene();
  const pl1 = new THREE.PointLight(0xfee3b1, 2);
  pl1.position.set(-20, 20, 20);
  // scene.add(pl1);
  
  const controls = new OrbitControls(camera,renderer.domElement)
  controls.target.set(0,0.5,0)
  
  const clock = new THREE.Clock();
  
  tex["smoke"] = texture_loader.load(
      ""
  );
  
  tex["fire"] = texture_loader.load(
      ""
  );
  
  tex["grass"] = texture_loader.load(
      ""
  );
  
  tex["floor"] = texture_loader.load(
      ""
  );
  tex["floor"].wrapS = tex["floor"].wrapT = THREE.RepeatWrapping;
  tex["floor"].repeat.set(20, 20);
  
  vs["sprite"] = `
  
  
  attribute vec3 offset;
  attribute vec2 scale;
  attribute vec4 quaternion;
  attribute float rotation;
  attribute vec4 color;
  attribute float blend;
  attribute float texture;
  uniform float time;
  varying vec2 vUv;
  varying vec4 vColor;
  varying float vBlend;
  varying float num;
  vec3 localUpVector=vec3(0.0,1.0,0.0);
  
  
  void main(){
  
  
  float angle=time*rotation;
  vec3 vRotated=vec3(position.x*scale.x*cos(angle)-position.y*scale.y*sin(angle),position.y*scale.y*cos(angle)+position.x*scale.x*sin(angle),position.z);
  
  
  vUv=uv;
  vColor=color;
  vBlend=blend;
  num=texture;
  
  
  vec3 vPosition;
  
  
  
  
  /*
  vec3 vLook=normalize(offset-cameraPosition);
  vec3 vRight=normalize(cross(vLook,localUpVector));
  vec3 vUp=normalize(cross(vLook,vRight));
  vPosition=vRight*vRotated.x+vUp*vRotated.y+vLook*vRotated.z;
  */
  
  
  vec3 vLook=offset-cameraPosition;
  vec3 vRight=normalize(cross(vLook,localUpVector));
  vPosition=vRotated.x*vRight+vRotated.y*localUpVector+vRotated.z;
  
  
  
  gl_Position=projectionMatrix*modelViewMatrix*vec4(vPosition+offset,1.0);
  
  
  }
  
  
  `;
  
  fs["sprite"] = `
  
  
  const int count=3;
  uniform sampler2D map[count];
  varying vec2 vUv;
  varying vec4 vColor;
  varying float vBlend;
  varying float num;
  
  
  void main(){
  
  
  if(num==0.0){ gl_FragColor=texture2D(map[0],vUv)*vColor; }
  else if(num==1.0){ gl_FragColor=texture2D(map[1],vUv)*vColor; }
  else if(num==2.0){ gl_FragColor=texture2D(map[2],vUv)*vColor; }
  
  
  gl_FragColor.rgb*=gl_FragColor.a;
  gl_FragColor.a*=vBlend;
  
  
  }
  
  
  `;
  
  var particles = [];
  
  // ____________________ GRASS ____________________
  
  var particles_grass_a = [];
  
  particles_grass_a.push({
      offset: [10, 2, 0],
      scale: [4, 4],
      quaternion: [0, 0, 0, 4],
      rotation: 0,
      color: [1, 1, 1, 1],
      blend: 1,
      texture: 2,
  });
  
  for (var n = 0; n < 100; n++) {
      var scale = Math.random() * 0.5 + 0.5;
      particles_grass_a.push({
          offset: [Math.random() * 20 - 10, scale / 2, Math.random() * 20 - 10],
          scale: [scale, scale],
          quaternion: [0, 0, 0, 4],
          rotation: 0,
          color: [1, 1, 1, 1],
          blend: 1,
          texture: 2,
      });
  }
  
  // ____________________ SMOKE ____________________
  
  var wind_x = 0.002;
  var wind_y = 0;
  var wind_z = 0;
  
  var particles_smoke_a = [];
  
  var particles_emmiter = [];
  
  particles_emmiter.push({
      position: { x: -2, y: 0, z: -4 },
      radius_1: 0.02,
      radius_2: 1,
      radius_height: 5,
      add_time: 0.1,
      elapsed: 0,
      live_time_from: 7,
      live_time_to: 7.5,
      opacity_decrease: 0.008,
      rotation_from: 0.5,
      rotation_to: 1,
      speed_from: 0.005,
      speed_to: 0.01,
      scale_from: 0.2,
      scale_increase: 0.004,
      color_from: [2, 2, 2],
      color_to: [0, 0, 0],
      color_speed_from: 0.4,
      color_speed_to: 0.4,
      brightness_from: 1,
      brightness_to: 1,
      opacity: 1,
      blend: 0.8,
      texture: 1,
  });
  
  particles_emmiter.push({
      position: { x: 0, y: 0, z: -4 },
      radius_1: 0.02,
      radius_2: 1,
      radius_height: 5,
      add_time: 0.1,
      elapsed: 0,
      live_time_from: 10,
      live_time_to: 10.5,
      opacity_decrease: 0.008,
      rotation_from: 0.5,
      rotation_to: 1,
      speed_from: 0.005,
      speed_to: 0.01,
      scale_from: 0.2,
      scale_increase: 0.004,
      color_from: [0.1, 0.1, 0.1],
      color_to: [0.1, 0.1, 0.1],
      color_speed_from: 1,
      color_speed_to: 1,
      brightness_from: 1,
      brightness_to: 1,
      opacity: 1,
      blend: 1,
      texture: 0,
  });
  
  particles_emmiter.push({
      position: { x: 2, y: 0, z: -4 },
      radius_1: 0.02,
      radius_2: 0.4,
      radius_height: 5,
      add_time: 0.1,
      elapsed: 0,
      live_time_from: 4,
      live_time_to: 4.5,
      opacity_decrease: 0.004,
      rotation_from: 2,
      rotation_to: 3,
      speed_from: 0.005,
      speed_to: 0.01,
      scale_from: 0.1,
      scale_increase: 0.003,
      color_from: [1, 1, 1],
      color_to: [1, 1, 1],
      color_speed_from: 1,
      color_speed_to: 1,
      brightness_from: 1.0,
      brightness_to: 1,
      opacity: 0.4,
      blend: 0.5,
      texture: 0,
  });
  
  particles_emmiter.push({
      position: { x: 4, y: 0, z: -4 },
      radius_1: 2,
      radius_2: 2,
      radius_height: 5,
      add_time: 0.1,
      elapsed: 0,
      live_time_from: 1,
      live_time_to: 1.5,
      opacity_decrease: 0.004,
      rotation_from: 2,
      rotation_to: 3,
      speed_from: 0.005,
      speed_to: 0.01,
      scale_from: 0.0,
      scale_increase: 0.003,
      color_from: [1, 2, 1],
      color_to: [1, 1, 2],
      color_speed_from: 1,
      color_speed_to: 1,
      brightness_from: 1.0,
      brightness_to: 1,
      opacity: 0.4,
      blend: 0.7,
      texture: 0,
  });
  
  particles_emmiter.push({
      position: { x: 0, y: 1, z: 0 },
      radius_1: 0.02,
      radius_2: 1,
      radius_height: 5,
      add_time: 0.01,
      elapsed: 0,
      live_time_from: 1,
      live_time_to: 1.5,
      opacity_decrease: 0.008,
      rotation_from: 0.5,
      rotation_to: 1,
      speed_from: 0.005,
      speed_to: 0.01,
      scale_from: 0.2,
      scale_increase: 0.004,
      color_from: [2, 2, 2],
      color_to: [0, 0, 0],
      color_speed_from: 1,
      color_speed_to: 1,
      brightness_from: 1,
      brightness_to: 1,
      opacity: 1,
      blend: 0.8,
      texture: 1,
  });
  
  // ____________________ PARTICLES EMMITER EMMIT ____________________
  
  function particles_emmiter_emmit(item) {
      var radius_1 = item.radius_1 * Math.sqrt(Math.random());
      var theta = 2 * Math.PI * Math.random();
      var x_1 = item.position.x + radius_1 * Math.cos(theta);
      var z_1 = item.position.z + radius_1 * Math.sin(theta);
  
      var radius_2 = item.radius_2 * Math.sqrt(Math.random());
      var theta = 2 * Math.PI * Math.random();
      var x_2 = x_1 + radius_2 * Math.cos(theta);
      var z_2 = z_1 + radius_2 * Math.sin(theta);
  
      let direction_x = x_2 - x_1;
      let direction_y = item.radius_height;
      let direction_z = z_2 - z_1;
  
      var speed =
          Math.random() * (item.speed_to - item.speed_from) + item.speed_from;
  
      var divide =
          (1 /
              Math.sqrt(
                  direction_x * direction_x +
                      direction_y * direction_y +
                      direction_z * direction_z
              )) *
          speed;
      direction_x *= divide;
      direction_y *= divide;
      direction_z *= divide;
  
      var brightness =
          Math.random() * (item.brightness_to - item.brightness_from) +
          item.brightness_from;
  
      particles_smoke_a.push({
          offset: [x_1, item.position.y, z_1],
          scale: [item.scale_from, item.scale_from],
          quaternion: [direction_x, direction_y, direction_z, 3],
          rotation:
              Math.random() * (item.rotation_to - item.rotation_from) +
              item.rotation_from,
          color: [1, 1, 1, item.opacity],
          blend: item.blend,
          texture: item.texture,
          live:
              Math.random() * (item.live_time_to - item.live_time_from) +
              item.live_time_from,
          scale_increase: item.scale_increase,
          opacity_decrease: item.opacity_decrease,
          color_from: [
              item.color_from[0] * brightness,
              item.color_from[1] * brightness,
              item.color_from[2] * brightness,
          ],
          color_to: [
              item.color_to[0] * brightness,
              item.color_to[1] * brightness,
              item.color_to[2] * brightness,
          ],
          color_speed:
              Math.random() * (item.color_speed_to - item.color_speed_from) +
              item.color_speed_from,
          color_pr: 0,
      });
  }
  
  // ____________________ PERTICLES EMMITER UPDATE ____________________
  
  function particles_emmiter_update() {
      var item = particles_emmiter[4].position;
      item.x = Math.sin(time / 1) * 4;
      item.z = Math.cos(time / 1) * 4;
  
      var max = particles_emmiter.length;
  
      for (var n = 0; n < max; n++) {
          var item = particles_emmiter[n];
  
          var add = 0;
  
          item.elapsed += delta;
          add = Math.floor(item.elapsed / item.add_time);
          item.elapsed -= add * item.add_time;
          if (add > (0.016 / item.add_time) * 60 * 1) {
              item.elapsed = 0;
              add = 0;
          }
  
          while (add--) {
              particles_emmiter_emmit(item);
          }
      }
  
      var max = particles_smoke_a.length;
      var alive = new Array(max);
      var i = 0;
  
      for (var j = 0; j < max; j++) {
          var item = particles_smoke_a[j];
  
          if (item.color_pr < 1) {
              var color_r =
                  item.color_from[0] +
                  (item.color_to[0] - item.color_from[0]) * item.color_pr;
              var color_g =
                  item.color_from[1] +
                  (item.color_to[0] - item.color_from[1]) * item.color_pr;
              var color_b =
                  item.color_from[1] +
                  (item.color_to[0] - item.color_from[2]) * item.color_pr;
              item.color_pr += delta * item.color_speed;
              item.color[0] = color_r;
              item.color[1] = color_g;
              item.color[2] = color_b;
          } else {
              item.color[0] = item.color_to[0];
              item.color[1] = item.color_to[1];
              item.color[2] = item.color_to[2];
          }
  
          item.offset[0] += item.quaternion[0] + wind_x;
          item.offset[1] += item.quaternion[1] + wind_y;
          item.offset[2] += item.quaternion[2] + wind_z;
          item.scale[0] += item.scale_increase;
          item.scale[1] += item.scale_increase;
  
          if (item.live > 0) {
              item.live -= delta;
          } else {
              item.color[3] -= item.opacity_decrease;
          }
          if (item.color[3] > 0) {
              alive[i] = item;
              i++;
          }
      }
  
      alive.length = i;
      particles_smoke_a = alive;
  }
  
  // ____________________ PARTICLES UPDATE ____________________
  
  function particles_update() {
      particles_emmiter_update();
  
      particles = [];
  
      var max_1 = particles_smoke_a.length;
      particles.length = max_1;
      for (var n = 0; n < max_1; n++) {
          particles[n] = particles_smoke_a[n];
      }
  
      var max_2 = max_1 + particles_grass_a.length;
      particles.length = max_2;
      var i = 0;
      for (var n = max_1; n < max_2; n++) {
          particles[n] = particles_grass_a[i];
          i++;
      }
  
      var count = particles.length;
      var item = camera.position;
      var x = item.x;
      var y = item.y;
      var z = item.z;
  
      for (var n = 0; n < count; n++) {
          var item = particles[n].offset;
          particles[n].d = Math.sqrt(
              Math.pow(x - item[0], 2) +
                  Math.pow(y - item[1], 2) +
                  Math.pow(z - item[2], 2)
          );
      }
  
      particles.sort((a, b) => b.d - a.d);
  
      var offset = new Float32Array(count * 3);
      var scale = new Float32Array(count * 2);
      var quaternion = new Float32Array(count * 4);
      var rotation = new Float32Array(count);
      var color = new Float32Array(count * 4);
      var blend = new Float32Array(count);
      var texture = new Float32Array(count);
  
      for (var n = 0; n < count; n++) {
          // 1 VALUE
          var item = particles[n];
          rotation[n] = item.rotation;
          texture[n] = item.texture;
          blend[n] = item.blend;
  
          // 2 VALUE
          var p = n * 2;
          var one = p + 1;
          var i_scale = item.scale;
          scale[p] = i_scale[0];
          scale[one] = i_scale[1];
  
          // 3 VALUE
          var p = n * 3;
          var one = p + 1;
          var two = p + 2;
          var i_offset = item.offset;
          offset[p] = i_offset[0];
          offset[one] = i_offset[1];
          offset[two] = i_offset[2];
  
          // 4 VALUE
          var p = n * 4;
          var one = p + 1;
          var two = p + 2;
          var three = p + 3;
          var i_color = item.color;
          color[p] = i_color[0];
          color[one] = i_color[1];
          color[two] = i_color[2];
          color[three] = i_color[3];
          var i_quaternion = item.quaternion;
          quaternion[p] = i_quaternion[0];
          quaternion[one] = i_quaternion[1];
          quaternion[two] = i_quaternion[2];
          quaternion[three] = i_quaternion[3];
      }
  
      var item = mesh["sprite"].geometry.attributes;
      item.offset = new THREE.InstancedBufferAttribute(offset, 3).setUsage(
          THREE.DynamicDrawUsage
      );
      item.scale = new THREE.InstancedBufferAttribute(scale, 2).setUsage(
          THREE.DynamicDrawUsage
      );
      item.quaternion = new THREE.InstancedBufferAttribute(
          quaternion,
          4
      ).setUsage(THREE.DynamicDrawUsage);
      item.rotation = new THREE.InstancedBufferAttribute(
          rotation,
          1
      ).setUsage(THREE.DynamicDrawUsage);
      item.color = new THREE.InstancedBufferAttribute(color, 4).setUsage(
          THREE.DynamicDrawUsage
      );
      item.blend = new THREE.InstancedBufferAttribute(blend, 1).setUsage(
          THREE.DynamicDrawUsage
      );
      item.texture = new THREE.InstancedBufferAttribute(texture, 1).setUsage(
          THREE.DynamicDrawUsage
      );
  
      mesh["sprite"].geometry._maxInstanceCount = count;
  }
  
  var geometry = new THREE.InstancedBufferGeometry();
  geometry.setAttribute(
      "position",
      new THREE.Float32BufferAttribute(
          new Float32Array([
              -0.5, 0.5, 0, -0.5, -0.5, 0, 0.5, 0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0,
              -0.5, -0.5, 0,
          ]),
          3
      )
  );
  geometry.setAttribute(
      "uv",
      new THREE.Float32BufferAttribute(
          new Float32Array([0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0]),
          2
      )
  );
  geometry.setAttribute(
      "offset",
      new THREE.InstancedBufferAttribute(new Float32Array(), 3)
  );
  geometry.setAttribute(
      "scale",
      new THREE.InstancedBufferAttribute(new Float32Array(), 2)
  );
  geometry.setAttribute(
      "quaternion",
      new THREE.InstancedBufferAttribute(new Float32Array(), 4)
  );
  geometry.setAttribute(
      "rotation",
      new THREE.InstancedBufferAttribute(new Float32Array(), 1)
  );
  geometry.setAttribute(
      "color",
      new THREE.InstancedBufferAttribute(new Float32Array(), 4)
  );
  geometry.setAttribute(
      "blend",
      new THREE.InstancedBufferAttribute(new Float32Array(), 1)
  );
  geometry.setAttribute(
      "texture",
      new THREE.InstancedBufferAttribute(new Float32Array(), 1)
  );
  
  mat["sprite"] = new THREE.ShaderMaterial({
      uniforms: {
          map: { value: [tex["smoke"], tex["fire"], tex["grass"]] },
          time: { value: 0 },
      },
      vertexShader: vs["sprite"],
      fragmentShader: fs["sprite"],
      //side:THREE.DoubleSide,
      transparent: true,
      depthWrite: false,
      blending: THREE.CustomBlending,
      blendEquation: THREE.AddEquation,
      blendSrc: THREE.OneFactor,
      blendDst: THREE.OneMinusSrcAlphaFactor,
  });
  
  mesh["sprite"] = new THREE.Mesh(geometry, mat["sprite"]);
  mesh["sprite"].frustumCulled = false;
  mesh["sprite"].matrixAutoUpdate = false;
  mesh["sprite"].updateMatrixWorld = function () {};
  debugger
  scene.add(mesh["sprite"]);
  
  mat["floor"] = new THREE.MeshStandardMaterial({
      map: tex["floor"],
      bumpMap: tex["floor"],
      bumpScale: 0.01,
      metalness: 0.16,
  });
  
  mesh["floor"] = new THREE.Mesh(
      new THREE.BoxGeometry(20, 1, 20),
      mat["floor"]
  );
  mesh["floor"].position.y = -0.5;
//   scene.add(mesh["floor"]);
  
  scene.add(new THREE.AmbientLight(0xffffff, 3));
  
  var update_time = 0;
  window.ccc = scene
  
  function loop() {
      requestAnimationFrame(loop);
      delta = clock.getDelta();
      time = clock.elapsedTime.toFixed(2);
  
      var started = performance.now();
      particles_update();
  
      update_time -= delta;
  
      mat["sprite"].uniforms.time.value = clock.elapsedTime;
  
      renderer.render(scene, camera);
  }
  
  loop();
  
  /**
   * 名称: 烟雾效果
   * 作者: Three JS https://threejs.org/
  */
  })
  </script>
  
  <style scoped>
  /* 样式部分与之前相同，保持不变 */
  .scene-wrapper {
    position: relative;
    width: 100vw;
    height: 100vh;
  }
  </style>